package com.gzx.spring.boot.init;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

import com.gzx.risk.core.init.ExtInit;

/**
 * 注解解析：服务暴露、服务引入
 * 
 * @author wuyan_dxm
 * 
 */
@Service
public class BeanTagsChecker implements ApplicationContextAware {
    private ApplicationContext ctx;
    private GzxInitHelper extInitHelper = new GzxInitHelper();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ctx = applicationContext;
    }

    public void extInit(ApplicationContext ctx) {
        extInitHelper.extInit(ctx);
    }

    private GzxInitInfoBean toInfoBean(int order, Class<?> rootClass, Class<?> initClass, String initMethodName) {
        GzxInitInfoBean bean = new GzxInitInfoBean();
        bean.setOrder(order);
        bean.setRootClassName(rootClass.getName());
        bean.setInitClassName(initClass.getName());
        bean.setInitMethodName(initMethodName);
        return bean;
    }

    public List<GzxInitInfoBean> getInitInfo() throws Exception {
        List<GzxInitInfoBean> infoBeans = new ArrayList<>();
        for (Object realBean : extInitHelper.findInitBeans(ctx)) {
            ExtInit tag = realBean.getClass().getAnnotation(ExtInit.class);
            if (tag == null) {
                continue;
            }
            int order = tag.order();
            Class<?> rootClass = realBean.getClass();

            Class<?> beanClass = realBean.getClass();
            while (true) {
                if (beanClass == Object.class) {
                    break;
                }
                Method[] methods = beanClass.getDeclaredMethods();
                for (Method method : methods) {
                    ExtInit methodTag = method.getAnnotation(ExtInit.class);
                    if (methodTag != null) {
                        infoBeans.add(this.toInfoBean(order, rootClass, beanClass, method.getName()));
                    }
                }
                beanClass = beanClass.getSuperclass();
            }
        }
        Collections.sort(infoBeans, new Comparator<GzxInitInfoBean>() {

            @Override
            public int compare(GzxInitInfoBean o1, GzxInitInfoBean o2) {
                Integer order1 = o1.getOrder();
                Integer order2 = o2.getOrder();
                return order1.compareTo(order2);
            }
        });
        return infoBeans;
    }

}
